﻿#region The MIT License (MIT)
// The MIT License (MIT)
// Copyright (c) 2010 - 2013 Sovacode LLC
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#endregion

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Sovacode.RubiksCube.Common.Managers.Settings.Data;
using Sovacode.RubiksCube.Common.Service;
using Sovacode.RubiksCube.Common.ViewModel;

namespace Sovacode.RubiksCube.Common.Managers.Settings
{
    /// <summary>
    /// Interface for Settings Manager
    /// </summary>
    public interface ISettingsManager : IManager
    {
        #region Put setting

        #region Expression

        /// <summary>
        /// Put setting as <see cref="double"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutDoubleSetting(Expression<Func<double>> expression, double setting);

        /// <summary>
        /// Put setting as <see cref="int"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutInt32Setting(Expression<Func<int>> expression, int setting);

        /// <summary>
        /// Put setting as <see cref="string"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutStringSetting(Expression<Func<string>> expression, string setting);

        /// <summary>
        /// Put setting as <see cref="decimal"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutDecimalSetting(Expression<Func<decimal>> expression, decimal setting);

        /// <summary>
        /// Put setting as <see cref="char"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutCharSetting(Expression<Func<char>> expression, char setting);

        /// <summary>
        /// Put setting as <see cref="bool"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutBoolSetting(Expression<Func<bool>> expression, bool setting);

        #endregion

        #region Simple

        /// <summary>
        /// Put setting as <see cref="double"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutDoubleSetting(string settingName, double setting);

        /// <summary>
        /// Put setting as <see cref="int"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutInt32Setting(string settingName, int setting);

        /// <summary>
        /// Put setting as <see cref="string"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutStringSetting(string settingName, string setting);

        /// <summary>
        /// Put setting as <see cref="decimal"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutDecimalSetting(string settingName, decimal setting);

        /// <summary>
        /// Put setting as <see cref="char"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutCharSetting(string settingName, char setting);

        /// <summary>
        /// Put setting as <see cref="bool"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutBoolSetting(string settingName, bool setting);

        #endregion

        /// <summary>
        /// Put setting as specific type
        /// </summary>
        /// <typeparam name="T">Type of setting</typeparam>
        /// <param name="expression">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutSetting<T>(Expression<Func<T>> expression, T setting);

        /// <summary>
        /// Put setting as specific type
        /// </summary>
        /// <typeparam name="T">Type of setting</typeparam>
        /// <param name="settingName">Setting name in config file</param>
        /// <param name="setting">Value of setting</param>
        void PutSetting<T>(string settingName, T setting);

        #endregion

        #region Get Setting

        #region Expression

        /// <summary>
        /// Get setting from config file as <see cref="double"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        double GetDoubleSetting(Expression<Func<double>> expression);

        /// <summary>
        /// Get setting from config file as <see cref="int"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        int GetInt32Setting(Expression<Func<int>> expression);

        /// <summary>
        /// Get setting from config file as <see cref="string"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        string GetStringSetting(Expression<Func<string>> expression);

        /// <summary>
        /// Get setting from config file as <see cref="decimal"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        decimal GetDecimalSetting(Expression<Func<decimal>> expression);

        /// <summary>
        /// Get setting from config file as <see cref="char"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        char GetCharSetting(Expression<Func<char>> expression);

        /// <summary>
        /// Get setting from config file as <see cref="bool"/>
        /// </summary>
        /// <param name="expression">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        bool GetBooleanSetting(Expression<Func<bool>> expression);

        #endregion

        #region Simple

        /// <summary>
        /// Get setting from config file as <see cref="double"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        double GetDoubleSetting(string settingName);

        /// <summary>
        /// Get setting from config file as <see cref="int"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        int GetInt32Setting(string settingName);

        /// <summary>
        /// Get setting from config file as <see cref="string"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        string GetStringSetting(string settingName);

        /// <summary>
        /// Get setting from config file as <see cref="decimal"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        decimal GetDecimalSetting(string settingName);

        /// <summary>
        /// Get setting from config file as <see cref="char"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        char GetCharSetting(string settingName);

        /// <summary>
        /// Get setting from config file as <see cref="bool"/>
        /// </summary>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        bool GetBooleanSetting(string settingName);

        #endregion


        /// <summary>
        /// Get setting from config file as specific type
        /// </summary>
        /// <typeparam name="T">Type of setting</typeparam>
        /// <param name="expression">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        T GetSetting<T>(Expression<Func<T>> expression);

        /// <summary>
        /// Get setting from config file as specific type
        /// </summary>
        /// <typeparam name="T">Type of setting</typeparam>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Value of setting</returns>
        T GetSetting<T>(string settingName);

        #endregion

        #region Connections

        /// <summary>
        /// Put Data Access Settings in config. It could be a connection string or something else.
        /// </summary>
        /// <param name="connections"><see cref="IList{T}"/> of <see cref="DataAccessSetting"/></param>
        void SaveConnectionString(IList<DataAccessSetting> connections);
        
        /// <summary>
        /// Get Data Access Settings from config back.
        /// </summary>
        /// <returns><see cref="IList{T}"/> of <see cref="DataAccessSetting"/>></returns>
        IList<DataAccessSetting> LoadConnectionStrings();

        #endregion

        #region List wrapper

        /// <summary>
        /// Put <see cref="IList{T}"/> into config file
        /// </summary>
        /// <typeparam name="T">Type of setting</typeparam>
        /// <param name="list"><see cref="IList{T}"/></param>
        /// <param name="settingName">Setting name in config file</param>
        void SaveList<T>(IList<T> list, string settingName);

        /// <summary>
        /// Get <see cref="IList{T}"/> from config file back
        /// </summary>
        /// <typeparam name="T">Type of setting</typeparam>
        /// <param name="settingName">Setting name in config file</param>
        /// <returns>Список</returns>
        IList<T> RestoreList<T>(string settingName);

        #endregion

        /// <summary>
        /// Save settings
        /// </summary>
        void SaveSettings();

        /// <summary>
        /// Run Setting Dialog for view model <see cref="IViewModelTop"/>
        /// </summary>
        /// <typeparam name="T"><see cref="IViewModelTop"/></typeparam>
        /// <param name="view"><see cref="IViewModelTop"/></param>
        /// <returns><see cref="WindowResult"/></returns>
        WindowResult ShowSettings<T>(T view)
            where T : IViewModelTop;
    }
}